package com.cskaoyan.javase.oop2._2polymorphic._3exercise;
/**
 * 读程序题
 * 对于"对象名点成员方法",方法的调用:
 *      1.首先要看引用的数据类型,因为引用决定究竟能够调用哪些方法.
 *      如果引用是父类类型,那么就需要看父类
 *      如果引用是子类类型,那么就需要看父类 + 子类
 *
 *      2.引用看完之后,要考虑对象的类型,如果对象是一个子类类型,并且调用的方法在子类中重写了
 *      那么调用的结果是子类的行为
 *
 *      3.除了以上原则以外,因为方法调用时,实参和形参数据类型之间存在自动类型转换,那么就有可能出现多个方法都能够方法调用的情况,这时考虑就近原则:
 *      优先考虑不类型转换的,优先直接匹配的
 *      如果没有直接匹配的,要考虑类型转换次数少的
 *
 * @since 15:50
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo2 {
    public static void main(String[] args) {
        /*
            父类引用指向父类对象
            这说明a1只能调用父类A中的方法
            方法的结果也只能是A类中的结果
          */
        A a1 = new A();
        /*
            父类引用指向子类对象
            这说明a2只能调用父类A中的方法
            但是方法的结果就有可能是子类B中的结果
                当子类B重写了父类中的方法时
         */
        A a2 = new B();
        /*
            子类引用指向子类对象
            这时匹配的范围就是父类 + 子类
            而一旦匹配成功,如果该方法在子类中存在,那就是子类行为,如果不存在,说明方法继承自父类,那就体现父类的行为
         */
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.println("1--" + a1.show(b)); // AA
        System.out.println("2--" + a1.show(c)); // AA
        System.out.println("3--" + a1.show(d)); // AD
        System.out.println("4--" + a2.show(b)); // BA
        System.out.println("5--" + a2.show(c)); // BA
        System.out.println("6--" + a2.show(d)); // AD
        System.out.println("7--" + b.show(b)); // BB
        System.out.println("8--" + b.show(c)); // BB
        System.out.println("9--" + b.show(d)); // AD
    }
}

class A {
    // 父类中独有的show方法
    public String show(D obj) {
        return ("A and D");
    }

    public String show(A obj) {
        return ("A and A");
    }
}

class B extends A {
    // 子类中独有的show方法
    public String show(B obj) {
        return ("B and B");
    }

    @Override
    public String show(A obj) {
        return ("B and A");
    }
}

class C extends B {
}

class D extends B {
}